package com.bocloud.cmp.driver.providers.vmware;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.bocloud.cmp.driver.providers.VdcDriver;
import com.bocloud.cmp.model.ClusterModel;
import com.bocloud.cmp.model.HostModel;
import com.bocloud.cmp.model.VDCModel;
import com.bocloud.common.model.BsmResult;
import com.google.common.collect.Lists;
import com.vmware.vim25.DatastoreSummary;
import com.vmware.vim25.HostListSummary;
import com.vmware.vim25.HostSystemConnectionState;
import com.vmware.vim25.mo.ClusterComputeResource;
import com.vmware.vim25.mo.ComputeResource;
import com.vmware.vim25.mo.Datacenter;
import com.vmware.vim25.mo.Datastore;
import com.vmware.vim25.mo.HostSystem;
import com.vmware.vim25.mo.InventoryNavigator;
import com.vmware.vim25.mo.ManagedEntity;

/**
 * vmware数据中心操作接口实现类
 * 
 * @author weiwei
 *
 */
public class VmwareVdcDriver extends VmwareDriver implements VdcDriver {

	private static Logger logger = LoggerFactory.getLogger(VmwareVdcDriver.class);

	public VmwareVdcDriver() {
		super();
	}

	/**
	 * @param endpoint
	 * @param username
	 * @param password
	 */
	public VmwareVdcDriver(String endpoint, String username, String password) {
		super(endpoint, username, password);
	}

	@Override
	public BsmResult list() {
		List<VDCModel> dcList = Lists.newArrayList();
		try {
			ManagedEntity[] dcEntities = new InventoryNavigator(this.getRootFolder()).searchManagedEntities(DC);
			if (null != dcEntities) {
				for (ManagedEntity dcEntity : dcEntities) {
					VDCModel model = assembleDc(dcEntity);
					dcList.add(model);
				}
			}
		} catch (Exception e) {
			logger.error("sync info error:", e);
			return new BsmResult(false, "同步失败");
		} finally {
			this.getServiceInstance().getServerConnection().logout();
		}
		return new BsmResult(true, dcList, "success");
	}

	/**
	 * 组装数据中心相关元数据
	 * 
	 * @param vdcs
	 * @param entity
	 * @throws Exception
	 */
	public VDCModel assembleDc(ManagedEntity entity) throws Exception {
		Datacenter datacenter = (Datacenter) entity;
		VDCModel vdc = new VDCModel(datacenter.getName(), 0l, 0l, 0l, 0l, 0l, 0l, null, null, null,
				datacenter.getMOR().getVal());
		List<ClusterModel> clusters = Lists.newArrayList();
		List<HostModel> hosts = Lists.newArrayList();
		ManagedEntity[] hostEntities = datacenter.getHostFolder().getChildEntity();
		if (null != hostEntities) {
			for (ManagedEntity hostEntity : hostEntities) {
				if (hostEntity instanceof ClusterComputeResource) {
					ClusterComputeResource cluster = (ClusterComputeResource) hostEntity;
					clusters.add(assembleCluster(cluster));
				} else if (hostEntity instanceof ComputeResource) {
					ComputeResource hostSystem = (ComputeResource) hostEntity;
					hosts.add(assembleHost(hostSystem.getHosts()[0]));
				}
			}
		}
		Long cpuTotal = 0l;
		Long memTotal = 0l;
		Long diskTotal = 0l;
		Long cpuUsed = 0l;
		Long memUsed = 0l;
		Long diskUsed = 0l;
		for (ClusterModel clusterModel : clusters) {
			cpuTotal += clusterModel.getCpuTotal();
			memTotal += clusterModel.getMemTotal();
			diskTotal += clusterModel.getDiskTotal();
			cpuUsed += clusterModel.getCpuUsed();
			memUsed += clusterModel.getMemUsed();
			diskUsed += clusterModel.getDiskUsed();
		}
		for (HostModel hostModel : hosts) {
			cpuTotal += hostModel.getCpuTotal();
			memTotal += hostModel.getMemTotal();
			diskTotal += hostModel.getDiskTotal();
			cpuUsed += hostModel.getCpuUsed();
			memUsed += hostModel.getMemUsed();
			diskUsed += hostModel.getDiskUsed();
		}
		vdc.setCpuTotal(cpuTotal);
		vdc.setDiskTotal(diskTotal);
		vdc.setMemTotal(memTotal);
		vdc.setCpuUsed(cpuUsed);
		vdc.setMemUsed(memUsed);
		vdc.setDiskUsed(diskUsed);
		return vdc;
	}

	/**
	 * 组装主机集群相关元数据
	 * 
	 * @param entity
	 * @throws Exception
	 */
	public ClusterModel assembleCluster(ClusterComputeResource entity) throws Exception {
		ClusterModel cluster = new ClusterModel();
		cluster.setName(entity.getName());
		cluster.setClusterVal(entity.getMOR().getVal());
		HostSystem[] hostSystems = entity.getHosts();
		List<HostModel> hosts = Lists.newArrayList();
		if (null != hostSystems) {
			for (HostSystem hostSystem : hostSystems) {
				hosts.add(assembleHost(hostSystem));
			}
		}
		Long cpuTotal = 0l;
		Long memTotal = 0l;
		Long diskTotal = 0l;
		Long cpuUsed = 0l;
		Long memUsed = 0l;
		Long diskUsed = 0l;
		int cpuCore = 0;
		for (HostModel hostModel : hosts) {
			cpuTotal += hostModel.getCpuTotal();
			memTotal += hostModel.getMemTotal();
			diskTotal += hostModel.getDiskTotal();
			cpuUsed += hostModel.getCpuUsed();
			memUsed += hostModel.getMemUsed();
			diskUsed += hostModel.getDiskUsed();
			cpuCore += hostModel.getCpuCore();
		}
		cluster.setCpuTotal(cpuTotal);
		cluster.setMemTotal(memTotal);
		cluster.setDiskTotal(diskTotal);
		cluster.setCpuUsed(cpuUsed);
		cluster.setMemUsed(memUsed);
		cluster.setDiskUsed(diskUsed);
		cluster.setCpuCore(cpuCore);
		return cluster;
	}

	/**
	 * 组装主机集群相关元数据
	 * 
	 * @param host
	 * @throws Exception
	 */
	public HostModel assembleHost(HostSystem host) throws Exception {
		HostModel hostModel = new HostModel();
		HostListSummary summary = host.getSummary();
		hostModel.setCpuNum((int) summary.getHardware().getNumCpuPkgs());
		hostModel.setCpuCore((int) summary.getHardware().getNumCpuCores());
		hostModel.setCpuTotal(Long.valueOf(summary.getHardware().getCpuMhz()) * summary.getHardware().getNumCpuCores());
		HostSystemConnectionState connState = host.getSummary().getRuntime().getConnectionState();// 物理机连接状态
		if (connState.equals(HostSystemConnectionState.connected)) {
			hostModel.setCpuUsed(summary.getQuickStats().getOverallCpuUsage().longValue());
			hostModel.setMemUsed(summary.getQuickStats().getOverallMemoryUsage().longValue());
		} else {
			hostModel.setCpuUsed(0L);
			hostModel.setMemUsed(0L);
		}
		BigDecimal memory = new BigDecimal(host.getHardware().getMemorySize());
		hostModel.setMemTotal(memory.divide(new BigDecimal(1024 * 1024), 1, RoundingMode.HALF_UP).longValue());
		Datastore[] datastores = host.getDatastores();
		Long diskCapacity = 0l;
		Long freeCapacity = 0l;
		if (null != datastores) {
			for (Datastore datastore : datastores) {
				DatastoreSummary datastoreSummary = datastore.getSummary();
				diskCapacity += datastoreSummary.getCapacity();
				freeCapacity += datastoreSummary.getFreeSpace();
			}
		}
		BigDecimal capacity = new BigDecimal(diskCapacity);
		BigDecimal freedisk = new BigDecimal(freeCapacity);
		diskCapacity = capacity.divide(new BigDecimal(1024 * 1024 * 1024), 1, RoundingMode.HALF_UP).longValue();
		freeCapacity = freedisk.divide(new BigDecimal(1024 * 1024 * 1024), 1, RoundingMode.HALF_UP).longValue();
		hostModel.setDiskTotal(diskCapacity);
		hostModel.setDiskUsed(diskCapacity - freeCapacity);
		return hostModel;
	}

}
